package org.jdcneter.system;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
 * @author miao
 * @since 2008-11-15
 *
 */
public class ServerLoader {
	private static Log log = LogFactory.getLog(ServerLoader.class);
	protected Properties props;
	
	protected URL libUrl;
	
	protected URL confUrl;
	
	protected URL pluginsUrl;
	
	protected URL deployUrl;
	
	protected List<URL> urlList = new ArrayList<URL>();
	
	private final static String DEFAULT_SERVER_TYPE = "org.jdstream.server.ServerImpl";
	
	public ServerLoader(final Properties props) throws Exception{
		
		if(props == null){
			throw new IllegalArgumentException("props is null");
		}
		this.props = props;
		URL homeUrl = getURL(ServerConfig.HOME_URL);
		if(homeUrl == null){
			throw new Exception("Missing configuration value for:"
					+ServerConfig.HOME_URL);
		}
		log.debug(homeUrl.getPath());
		libUrl = getURL(ServerConfig.LIB_URL);
		if(libUrl == null){
			libUrl = new URL(homeUrl,ServerConfig.LIB_URL_SUFFIX);
			props.put(ServerConfig.LIB_URL, libUrl);
		}
		confUrl = getURL(ServerConfig.CONF_URL);
		if(confUrl == null){
			confUrl = new URL(homeUrl,ServerConfig.CONF_URL_SUFFIX);
			props.put(ServerConfig.CONF_URL, confUrl);
		}
		pluginsUrl = getURL(ServerConfig.PLUGINS_URL);
		if(pluginsUrl == null){
			pluginsUrl = new URL(homeUrl,ServerConfig.PLUGINS_URL_SUFFIX);
			props.put(ServerConfig.PLUGINS_URL, pluginsUrl);
		}
		deployUrl = getURL(ServerConfig.DEPLOY_URL);
		if(deployUrl == null){
			deployUrl = new URL(homeUrl,ServerConfig.DEPLOY_URL_SUFFIX);
			props.put(ServerConfig.DEPLOY_URL, deployUrl);
		}
		log.debug(libUrl.toString());
		urlList = getUrls(libUrl.getPath());
		log.debug(urlList.size());
		urlList.addAll(getUrls(pluginsUrl.getPath()));
	}
	
	private URL getURL(final String name) throws MalformedURLException{
		String value = props.getProperty(name);
		if(value != null){
			if(!value.endsWith("/")){
				value += "/";
			}
			return new URL(value);
		}
		return null;
	}
	
	private List<URL> getUrls(final String fileName) throws MalformedURLException, IOException{
		List<URL> urls = new ArrayList<URL>();
		File file = new File(fileName);
		log.debug(file.exists());
		if(file.exists()){
			File[] jarFiles = file.listFiles(new JarFilter());			
			for(File jarFile : jarFiles){
				urls.add(jarFile.getCanonicalFile().toURI().toURL());
			}
		}
		return urls;
	}
	
	public Server load(final ClassLoader parent) throws Exception{
		Server server;
		ClassLoader oldCL = Thread.currentThread().getContextClassLoader();

			System.out.println(urlList.toArray().getClass().getName());

		try{
			URLClassLoader loader = new NoAnnotationURLClassLoader(urlList.toArray(new URL[urlList.size()]),parent);
			Thread.currentThread().setContextClassLoader(loader);
			String typeName = props.getProperty(ServerConfig.SERVER_TYPE,DEFAULT_SERVER_TYPE);
			server = createServer(typeName,loader);
		}finally{
			Thread.currentThread().setContextClassLoader(oldCL);
		}
		return server;
	}
	
	private Server createServer(final String typeName,final ClassLoader loader) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
		Class<?> type = loader.loadClass(typeName);
		Server server = (Server)type.newInstance();
		return server;
	}
	
	static class JarFilter implements FilenameFilter{
		public boolean accept(File dir,String name){
			return name.endsWith(".jar");
		}
	}

}
